

package AddressBook.Model;

import java.io.*;
import java.util.ArrayList;
import java.util.Scanner;

/**
 * The Class FileManager provides function to manage file
 */
public class FileManager {

    /**
     * This field stores the contact loaded
     */
    private ArrayList<Contact> contactList;
    /**
     * This field stores the column name of the csv file
     */
    private String[] headerFieldFile;
    /**
     * This field stores the delimeter used to segment the file
     */
    private static final String DELIMITER = ";";


    /**
     * This method allows to load the specified file and returns an arrayList of contact
     *
     * @param selectedFile The file to load
     * @return An arrayList of contacts
     * @throws java.io.FileNotFoundException If the file was not found
     * @throws java.io.EOFException          If the file is empty
     */
    public ArrayList<Contact> load(File selectedFile) throws FileNotFoundException, EOFException {

        Scanner inputStream = new Scanner(new FileInputStream(selectedFile));
        contactList = new ArrayList<Contact>();

        if (inputStream.hasNextLine()) {
            headerFieldFile = inputStream.nextLine().split(DELIMITER);

            while (inputStream.hasNextLine()) {
                String row = inputStream.nextLine();
                Contact temporaryContact = splitRow(row);
                contactList.add(temporaryContact);
            }
        } else throw new EOFException("File Empty");
        return contactList;
    }

    /**
     * This method allows to save an contactList to an csv file
     * @param selectedFile The file to save
     * @param contactList The desired contactList
     * @throws FileNotFoundException If The file was not found
     */
    public void save(File selectedFile, ArrayList<Contact> contactList) throws FileNotFoundException {
        PrintWriter outputStreamName = new PrintWriter(new FileOutputStream(selectedFile));
        if (headerFieldFile != null) {
            for (int i = 0; i < headerFieldFile.length - 1; ++i) outputStreamName.print(headerFieldFile[i] + DELIMITER);
            outputStreamName.println(headerFieldFile[headerFieldFile.length - 1]);
        }

        for (Contact i : contactList) {
            outputStreamName.print(i.getFirstName() + DELIMITER);
            outputStreamName.print(i.getLastName() + DELIMITER);
            outputStreamName.print(i.getGroupName() + DELIMITER);
            outputStreamName.print(i.getHomeAddress() + DELIMITER);
            outputStreamName.print(i.getCompagnyAddress() + DELIMITER);
            outputStreamName.print(i.getPersonalPhone() + DELIMITER);
            outputStreamName.print(i.getProfessionalPhone() + DELIMITER);
            outputStreamName.print(i.getHomePage() + DELIMITER);
            outputStreamName.print(i.getEmail() + DELIMITER);
            outputStreamName.println(i.getUriPicture());

        }

        outputStreamName.close();
    }


    /**
     * This method allows to split a row into the associated contact
     *
     * @param row The row to split
     * @return The associated contact
     * @throws IllegalArgumentException If the row is empty
     */
    private Contact splitRow(String row) throws IllegalArgumentException {
        if (row.length() > 0) {
            String[] columns = row.split(";");
            Contact temporaryContact = new Contact();
            if (!columns[0].isEmpty()) temporaryContact.setFirstName(columns[0].trim());
            if (!columns[1].isEmpty()) temporaryContact.setLastName(columns[1].trim());
            if (!columns[2].isEmpty()) temporaryContact.setGroup(columns[2].trim());
            if (!columns[3].isEmpty()) temporaryContact.setHomeAddress(columns[3].trim());
            if (!columns[4].isEmpty()) temporaryContact.setCompagnyAddress(columns[4].trim());
            if (!columns[5].isEmpty()) temporaryContact.setPersonalPhone(columns[5].trim());
            if (!columns[6].isEmpty()) temporaryContact.setProfessionalPhone(columns[6].trim());
            if (!columns[7].isEmpty()) temporaryContact.setHomePage(columns[7].trim());
            if (!columns[8].isEmpty()) temporaryContact.setEmail(columns[8].trim());
            if (!columns[9].isEmpty()) temporaryContact.setUriPicture(columns[9].trim());


            return temporaryContact;
        } else throw new IllegalArgumentException("Empty row");

    }

    /**
     * This method allows to serialize an contact list
     * @param fileToWrite The file to write
     * @param contactList The desired contact list
     * @throws IOException
     */
    public void serializeItemList(File fileToWrite, ArrayList<Contact> contactList) throws IOException {

        FileOutputStream fos = new FileOutputStream(fileToWrite);
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        try {
            oos.writeObject(contactList);
            oos.flush();
        } finally {
            try {
                oos.close();
            } finally {
                fos.close();
            }
        }
    }

    /**
     * This method allows to deserialize a specified file into an contact list
     * @param fileToRead The file to read
     * @return An contact List
     * @throws IOException
     * @throws ClassNotFoundException If the class cast has failed
     * @throws NullPointerException
     */
    public ArrayList<Contact> deserializeItemList(File fileToRead) throws IOException, ClassNotFoundException, NullPointerException {

        ArrayList<Contact> contactList;
        FileInputStream fis = new FileInputStream(fileToRead);
        ObjectInputStream ois = new ObjectInputStream(fis);
        try {
            contactList = (ArrayList<Contact>) ois.readObject();
        } finally {
            try {
                ois.close();
            } finally {
                fis.close();
            }
        }
        if (contactList != null) {
            return contactList;
        } else throw new NullPointerException();

    }
}
